﻿using System;
using System.Collections.Generic;
using System.Net;
using __ts.Core.Session;

/*
 *  author: able
 *  @2012/2/20 15:37:58
 * 
 */
namespace __ts.Core.Api
{
    /// <summary>
    /// 
    /// </summary>
    public enum SessionState
    {
        CREATED, CONNECTED, CLOSING, CLOSED, SECURING, SECURED
    }

    /// <summary>
    /// 
    /// </summary>
    public interface IoSession
    {
        /// <summary>
        /// Gets the session ID.
        /// </summary>
        string SessionID { get; }

        /// <summary>
        /// Gets the identity key.
        /// In most case, IdentityKey is same as SessionID
        /// </summary>
        string IdentityKey { get; }

        /// <summary>
        /// Returns the socket address of remote peer.
        /// </summary>
        IPEndPoint RemoteAddress { get; }

        /// <summary>
        /// Gets the local address of the local peer.
        /// </summary>
        IPEndPoint LocalAddress { get; }

        /// <summary>
        /// Gets the service this session is attached to.
        /// </summary>
        IoService GetService { get; }

        /// <summary>
        /// Tells if the session is currently closed.
        /// </summary>
        bool isClosed { get; }

        /// <summary>
        /// Tells if the session is being closed.
        /// </summary>
        bool isClosing { get; }

        /// <summary>
        /// Tells if the session is currently connected and able to process incoming requests and to send outgoing responses.
        /// </summary>
        bool isConnected { get; }

        /// <summary>
        /// Tells if the session is created.
        /// </summary>
        bool isCreated { get; }

        /// <summary>
        /// Tells if the session is processing a SSL/TLS handshake.
        /// </summary>
        bool isSecuring { get; }

        /// <summary>
        /// Tells if the session is belonging to a secured connection.
        /// </summary>
        bool isSecured { get; }

        /// <summary>
        /// Changes the session's state from the current state to a new state. Not all the
        /// transition are allowed. Here is the list of all the possible transitions:<br/>
        /// <ul>
        ///     <li>CREATED   -> CONNECTED</li>
        ///     <li>CREATED   -> SECURING</li>
        ///     <li>CREATED   -> CLOSING</li>
        ///     <li>CONNECTED -> SECURING</li>
        ///     <li>CONNECTED -> CLOSING</li>
        ///     <li>SECURING  -> SECURED</li>
        ///     <li>SECURING  -> CLOSING</li>
        ///     <li>SECURED   -> CONNECTED</li>
        ///     <li>SECURED   -> SECURING</li>
        ///     <li>SECURED   -> CLOSING</li>
        ///     <li>CLOSING   -> CLOSED</li>
        ///     </ul>
        /// </summary>
        /// <param name="newState"></param>
        void changeState(SessionState newState);

        /// <summary>
        /// Initializes the SSL/TLS environment for this session.
        /// </summary>
        /// <param name="sslContext"></param>
        // void initSecure(SSLContext sslContext);

        /// <summary>
        /// Tells if the session is using SSL/TLS.
        /// </summary>
        /// <returns></returns>
        bool isConnectedSecured();

        /// <summary>
        /// 
        /// </summary>
        /// <param name="immediately"></param>
        void Close(bool immediately);

        /// <summary>
        /// Suspends read operations for this session.
        /// </summary>
        void suspendRead();

        /// <summary>
        /// Suspends write operations for this session.
        /// </summary>
        void suspendWrite();

        /// <summary>
        /// Resumes read operations for this session.
        /// </summary>
        void resumeRead();

        /// <summary>
        /// Resumes write operations for this session.
        /// </summary>
        void resumeWrite();

        /// <summary>
        /// Is read operation is suspended for this session.
        /// </summary>
        /// <returns></returns>
        bool isReadSuspended();

        /// <summary>
        /// Is write operation is suspended for this session.
        /// </summary>
        /// <returns></returns>
        bool isWriteSuspended();

        /// <summary>
        /// Gets the total number of bytes read for this session since it was created.
        /// </summary>
        /// <returns></returns>
        long getReadBytes();

        /// <summary>
        /// Gets the total number of bytes written for this session since it was created.
        /// </summary>
        /// <returns></returns>
        long getWrittenBytes();

        /// <summary>
        /// Gets the session configuration, it where the idle timeout are set and other transport specific configuration.
        /// </summary>
        /// <returns></returns>
        IoSessionConfig getConfig();

        /// <summary>
        /// The session's creation time.
        /// </summary>
        /// <returns></returns>
        long getCreationTime();

        /// <summary>
        /// Returns the time in millisecond when I/O occurred lastly (either read or write).
        /// </summary>
        /// <returns></returns>
        long getLastIoTime();

        /// <summary>
        /// Returns the time in millisecond when the last I/O read occurred.
        /// </summary>
        /// <returns></returns>
        long getLastReadTime();

        /// <summary>
        /// Returns the time in millisecond when the last I/O write occurred.
        /// </summary>
        /// <returns></returns>
        long getLastWriteTime();

        /* SESSION WRITING */
        /**
         * Enqueue a message for writing. This method wont block ! The message will by asynchronously processed by the
         * filter chain and wrote to socket by the {@link SelectorProcessor}.
         * 
         */
        void write(Object message);

        /**
         * Same as {@link IoSession#write(Object)}, but provide a {@link IoFuture} for tracking the completion of this
         * write.
         * 
         * @param message the message to be processed and written
         * @return the {@link IoFuture} for tracking this asynchronous operation
         */
        IoFuture<bool> writeWithFuture(Object message);

        /**
         * Internal method for enqueue write request after filter chain processing
         * 
         * @param message the message to put in the write request
         * @return the created write request
         */
        WriteRequest enqueueWriteRequest(Object message);

        /**
         * Get the {@link Queue} of this session. The write queue contains the pending writes. This
         * method will lock the WriteQueue using the WriteLock lock. The {@link releaseWriteQueue()
         * method must be called when finished : <br/>
         * <code>
         *   try {
         *       Queue<WriteRequest> queue = session.acquireWriteQueue();
         *       ...
         *       // We use the queue here
         *       ...
         *   } finally {
         *       session.releaseWriteQueue();
         *   }
         * <code>
         * 
         * @return the write queue of this session
         */
        Queue<WriteRequest> acquireWriteQueue();

        /**
         * Release the WriteQueue after having acquired it with the {@link acquireWriteQeuee()} method.
         */
        void releaseWriteQueue();


        //         T getAttribute(AttributeKey<T> key, T defaultValue);
        //<T> T getAttribute(AttributeKey<T> key);
        //<T> T setAttribute(AttributeKey<? extends T> key, T value);
        //Set<AttributeKey<?>> getAttributeKeys();
        //public <T> T removeAttribute(AttributeKey<T> key);

    }
}